package com.atguigu.netty.simple;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.util.CharsetUtil;

import java.util.concurrent.TimeUnit;

/**
 * @author: 叶子
 * @date: 2022/02/08 11:25
 * 自定义一个handler 需要继承netty规定好的某个HandlerAdapter
 * 此时自定义的handler才能称为handler
 **/
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
//    读取数据事件（这里可以读取客户端发送的消息）

    /**
     * 1.ChannelHandlerContext ctx:上下文对象，含有管道pipeline，通道channel，地址
     * 2.Object msg: 客户端发送的数据，默认Object
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//        假设这里有一个耗时长的业务->异步执行->提交到该channel 对应的NioEventLoop的taskQueue中
//        解决方案1，用户程序自定义的普通任务
        ctx.channel().eventLoop().execute(new Runnable() {
            @Override
            public void run() {

                try {
                    Thread.sleep(10 * 1000);
                } catch (InterruptedException e) {
                    System.out.println("发生异常，异常信息：" + e.getMessage());
                }
                ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客户端...喵2", CharsetUtil.UTF_8));
            }
        });
        ctx.channel().eventLoop().execute(() -> {
            try {
                Thread.sleep(5 * 1000);
            } catch (InterruptedException e) {
                System.out.println("发生异常，异常信息：" + e.getMessage());
            }
            ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客户端...喵3", CharsetUtil.UTF_8));
            //在同一个线程中，这个任务需要在上面那个休眠的基础上累加，所以打印顺序 喵1，喵2，喵3
        });
        //以下两行为模拟耗时长的业务，演示阻塞，客户端先打印出喵2，再打印喵1
        // Thread.sleep(10*1000);
        // ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客户端...喵2",CharsetUtil.UTF_8));
//       用户自定义定时任务->该任务提交到 scheduleTaskQueue中
        ctx.channel().eventLoop().schedule(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5*1000);
                    ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客户端...喵4",CharsetUtil.UTF_8));
                } catch (Exception e) {
                    System.out.println("发生异常"+e.getMessage());
                }
            }
        }, 5, TimeUnit.SECONDS);
        System.out.println("go on ...");
//        System.out.println("服务器读取线程："+Thread.currentThread().getName());
//        System.out.println("server ctx = "+ctx);
//        System.out.println("看看Channel和pipeline的关系");
//        Channel channel = ctx.channel();
//        ChannelPipeline pipeline = ctx.pipeline();//本质是一个双向链表，出站入站
////    channel和pipeline是相互包含的关系，可以根据channel找到pipeline，也可以根据pipeline找到channel
//        //将msg转成ByteBuf,这里的ByteBuf是Netty提供的，不是NIO的ByteBuffer
//        ByteBuf buf = (ByteBuf) msg;
//        System.out.println("客户端发送的消息是："+buf.toString(CharsetUtil.UTF_8));
//        System.out.println("客户端地址是："+channel.remoteAddress());
    }

    //    数据读取完毕
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        //writeAndFlush是write+flush，将数据写入缓存，并刷新
//      通常需要对这个发送的数据进行编码
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客户端...喵1", CharsetUtil.UTF_8));
    }
//    处理异常，一般是需要关闭通道

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}